### @configure_input@

# Copyright (C) 2023-2025 Free Software Foundation, Inc.

# This file is part of GNU Emacs.

# GNU Emacs is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.

# GNU Emacs is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.

# You should have received a copy of the GNU General Public License
# along with GNU Emacs.  If not, see <https://www.gnu.org/licenses/>.

top_builddir = @top_builddir@
top_srcdir = @top_srcdir@
srcdir = @srcdir@
builddir = @builddir@
version = @version@

# Don't install movemail if mailutils are to be used.
emacs_use_mailutils = @emacs_use_mailutils@

# This is the host lib-src and lib, not the cross compiler's lib-src.
libsrc = ../lib-src
EXEEXT = @EXEEXT@

-include ${top_builddir}/src/verbose.mk

SHELL = @SHELL@
JAVAC = @JAVAC@
AAPT = @AAPT@
D8 = @D8@
ZIPALIGN = @ZIPALIGN@
JARSIGNER = @JARSIGNER@
APKSIGNER = @APKSIGNER@
JARSIGNER_FLAGS =
ANDROID_JAR = @ANDROID_JAR@
ANDROID_ABI = @ANDROID_ABI@
ANDROID_SDK_18_OR_EARLIER = @ANDROID_SDK_18_OR_EARLIER@
ANDROID_SDK_8_OR_EARLIER = @ANDROID_SDK_8_OR_EARLIER@
ZIP = @ZIP@
WARN_JAVAFLAGS = @WARN_JAVAFLAGS@
JAVAFLAGS = $(WARN_JAVAFLAGS) -classpath "$(ANDROID_JAR):$(srcdir)"
FIND_DELETE = @FIND_DELETE@

ifneq (,$(ANDROID_SDK_8_OR_EARLIER))
# gzip is invoked to compress installed .el and some .txt files, on SDK
# 8 and earlier, where ZIP compression is unavailable.
GZIP_PROG = @GZIP_PROG@
else
GZIP_PROG =
endif


# Android 4.3 and earlier require Emacs to be signed with a different
# digital signature algorithm.

ifneq (,$(ANDROID_SDK_18_OR_EARLIER))
JARSIGNER_FLAGS = -sigalg MD5withRSA -digestalg SHA1
else
JARSIGNER_FLAGS =
endif

# When building Emacs for Android 2.2, assets must not be compressed.
# Otherwise, the asset manager fails to extract files larger than 1
# MB.

ifneq (,$(ANDROID_SDK_8_OR_EARLIER))
AAPT_ASSET_ARGS = -0 ""
else
AAPT_ASSET_ARGS =
endif

SIGN_EMACS = -keystore $(srcdir)/emacs.keystore -storepass	\
	emacs1 $(JARSIGNER_FLAGS)
SIGN_EMACS_V2 = sign --v2-signing-enabled --ks			\
	$(srcdir)/emacs.keystore -debuggable-apk-permitted	\
	--ks-pass pass:emacs1

JAVA_FILES := $(wildcard $(srcdir)/org/gnu/emacs/*.java)
RESOURCE_FILES := $(foreach file,$(wildcard $(srcdir)/res/*),	\
		    $(wildcard $(file)/*))

# R.java is a file generated by the `aapt' utility containing
# constants that can then be used to locate ``resource identifiers''.
# It is not a regular file and should not be compiled as Java source
# code.  Instead, it is automatically included by the Java compiler.
RESOURCE_FILE := $(srcdir)/org/gnu/emacs/R.java

# EmacsConfig.java is a file that holds information regarding the set of
# shared libraries this binary links to, and similar build variables.
CONFIG_FILE := $(builddir)/org/gnu/emacs/EmacsConfig.java

# CLASS_FILES is what should actually be built and included in the
# resulting Emacs executable.  The Java compiler might generate more
# than one class file for each source file, so this only serves as a
# list of dependencies for Make.
CLASS_FILES := $(foreach file,$(JAVA_FILES),$(basename $(file)).class)

# Remove RESOURCE_FILE from JAVA_FILES, if it is already present.
JAVA_FILES := $(filter-out $(RESOURCE_FILE),$(JAVA_FILES))

# Compute the name for the Emacs application package.  This should be:
# emacs-<version>-<min-sdk>-<abi>.apk

ANDROID_MIN_SDK := @ANDROID_MIN_SDK@
APK_NAME := emacs-$(version)-$(ANDROID_MIN_SDK)-$(ANDROID_ABI).apk

# Whether or not the bundle is to be debuggable.
ANDROID_DEBUGGABLE := @ANDROID_DEBUGGABLE@

# Whether or not $(D8) is in fact the name of the `r8' optimizer binary.
IS_D8_R8 := @IS_D8_R8@

# How this stuff works.

# emacs.apk depends on emacs.apk-in, which is simply a ZIP archive
# containing the following files:
#  lib/$(ANDROID_ABI)/libemacs.so
#  lib/$(ANDROID_ABI)/libandroid-emacs.so
#  lib/$(ANDROID_ABI)/libctags.so
#  lib/$(ANDROID_ABI)/libetags.so
#  lib/$(ANDROID_ABI)/libhexl.so
#  lib/$(ANDROID_ABI)/libmovemail.so
#  lib/$(ANDROID_ABI)/librcs2log.so
#  lib/$(ANDROID_ABI)/libebrowse.so
#  assets/info/
#  assets/etc/
#  assets/lisp/

.PHONY: emacs.apk-in all
all: $(APK_NAME)

# Binaries to cross-compile.
CROSS_SRC_BINS := $(top_builddir)/cross/src/android-emacs
CROSS_LIBSRC_BINS := $(top_builddir)/cross/lib-src/ctags	\
		     $(top_builddir)/cross/lib-src/hexl		\
		     $(top_builddir)/cross/lib-src/ebrowse	\
		     $(top_builddir)/cross/lib-src/emacsclient	\
		     $(top_builddir)/cross/lib-src/etags
CROSS_LIBSRC_BINS_MOVEMAIL := $(top_builddir)/cross/lib-src/movemail
CROSS_EXEC_BINS := $(top_builddir)/exec/exec1 $(top_builddir)/exec/loader
CROSS_BINS = $(CROSS_SRC_BINS) $(CROSS_LIBSRC_BINS) $(CROSS_EXEC_BINS)

ifneq ($(emacs_use_mailutils),yes)
CROSS_LIBSRC_BINS := $(CROSS_LIBSRC_BINS) $(CROSS_LIBSRC_BINS_MOVEMAIL)
endif

# Libraries to cross-compile.
CROSS_LIBS = $(top_builddir)/cross/src/libemacs.so

# Make sure gnulib is built first!
# If not, then the recursive invocations of make below will try to
# build gnulib at the same time.
CROSS_ARCHIVES = $(top_builddir)/cross/lib/libgnu.a

# Third party libraries to compile.
-include $(top_builddir)/cross/ndk-build/ndk-build.mk

.PHONY: $(CROSS_BINS) $(CROSS_LIBS) $(CROSS_ARCHIVES)

# There should only be a single invocation of $(MAKE) -C
# $(top_srcdir)/cross for each directory under $(top_srcdir)/cross.
$(CROSS_SRC_BINS) $(CROSS_LIBS) &: $(CROSS_ARCHIVES)
	$(MAKE) -C $(top_builddir)/cross $(foreach file,	\
					   $(CROSS_SRC_BINS)	\
					   $(CROSS_LIBS),	\
					   src/$(notdir $(file)))

$(CROSS_LIBSRC_BINS) &: $(CROSS_ARCHIVES)
	$(MAKE) -C $(top_builddir)/cross $(foreach file,		\
					   $(CROSS_LIBSRC_BINS),	\
					   lib-src/$(notdir $(file)))

$(CROSS_ARCHIVES):
	$(MAKE) -C $(top_builddir)/cross lib/libgnu.a

# These two binaries are helpers used to execute binaries on Android
# 10 and later.

$(CROSS_EXEC_BINS) &:
	$(MAKE) -C $(top_builddir)/exec $(notdir $(CROSS_EXEC_BINS))

# This is needed to generate the ``.directory-tree'' file used by the
# Android emulations of readdir and faccessat.

$(libsrc)/asset-directory-tool:
	$(MAKE) -C $(libsrc) $(notdir $@)

# install_tmp is a directory used to generate emacs.apk-in.
# That is then packaged into $(APK_NAME).
# There is no need to depend on NDK_BUILD_SHARED as libemacs.so
# does already.

.PHONY: install_temp
install_temp: $(CROSS_BINS) $(CROSS_LIBS) $(RESOURCE_FILES)	\
  $(libsrc)/asset-directory-tool
	$(AM_V_GEN)
# Make the working directory for this stuff
	$(AM_V_SILENT) rm -rf install_temp
	$(AM_V_SILENT) mkdir -p install_temp/lib/$(ANDROID_ABI)
	$(AM_V_SILENT) mkdir -p install_temp/assets/etc
	$(AM_V_SILENT) mkdir -p install_temp/assets/lisp
	$(AM_V_SILENT) mkdir -p install_temp/assets/info
	$(AM_V_SILENT) mkdir -p install_temp/assets/bitmaps
# Install architecture independents to assets/etc, assets/lisp and
# assets/bitmaps
	$(AM_V_SILENT) cp -r $(top_srcdir)/lisp install_temp/assets
	$(AM_V_SILENT) cp -r $(top_srcdir)/etc install_temp/assets
	$(AM_V_SILENT) cp -r $(top_srcdir)/info install_temp/assets
	$(AM_V_SILENT) cp -r $(top_srcdir)/src/bitmaps install_temp/assets
# Replace etc/DOC generated by compiling Emacs for the build machine
# with etc/DOC from the cross-compiled Emacs.
	$(AM_V_SILENT) test -f $(top_builddir)/cross/etc/DOC	\
	  && cp -r $(top_builddir)/cross/etc/DOC		\
	     install_temp/assets/etc
# Remove undesirable files from those directories.
	$(AM_V_SILENT)						\
	for subdir in `find install_temp -type d -print`; do	\
	  chmod a+rx $${subdir} ;				\
	  rm -rf $${subdir}/.gitignore ;			\
	  rm -rf $${subdir}/.DS_Store ;				\
	  rm -rf $${subdir}/#* ;				\
	  rm -rf $${subdir}/.#* ;				\
	  rm -rf $${subdir}/*~ ;				\
	  rm -rf $${subdir}/*.orig ;				\
	  rm -rf $${subdir}/ChangeLog* ;			\
	  rm -rf $${subdir}/[mM]akefile*[.-]in ;		\
	  rm -rf $${subdir}/Makefile;				\
	done
# Compress files if AAPT otherwise will not.
	$(AM_V_SILENT)						\
	[ -z "${GZIP_PROG}" ] || {				\
	  echo "Compressing large *.el *.info etc. ..." &&	\
	  cd "install_temp/assets/lisp" &&			\
	  for f in `find . -name "*.elc" \( -size +1536 -o 	\
		      -size 1536 \) -print 			\
		    | sed 's/.elc$$/.el/'`; do			\
	    ${GZIP_PROG} -9n "$$f";				\
	  done;							\
	  ${GZIP_PROG} -9n "../etc/publicsuffix.txt";		\
	  find ../info -name "*.elc" -size 1536 -o -size +1536	\
	   | xargs ${GZIP_PROG} -9n ;				\
	}
# Produce metadata files providing build information and suchlike.
	$(AM_V_SILENT)						\
	{ (cd $(top_srcdir)					\
	   && git rev-parse HEAD || echo "Unknown")		\
	   && (git rev-parse --abbrev-ref HEAD 			\
	       || echo "Unknown") } 2> /dev/null >		\
	  install_temp/assets/version
	$(AM_V_SILENT)						\
	{ hostname; date +%s; } > install_temp/assets/build_info
# Produce the file index.
	$(AM_V_SILENT) $(libsrc)/asset-directory-tool 		\
	  install_temp/assets install_temp/assets/directory-tree\
	  $(if $(ANDROID_SDK_8_OR_EARLIER),--api-8)
# If the package targets Android 2.2, move compressible and
# non-compressible assets to separate directories.
	$(AM_V_SILENT)						\
	if [ -z "${ANDROID_SDK_8_OR_EARLIER}" ]; then :; else	\
	  echo "Moving large and gzipped files to separate directories...">&2;\
	  mkdir -p install_temp/assets_raw;			\
	  cd install_temp/assets;				\
	  mv directory-tree ../assets_raw;			\
	  find . \( -size +1536 -o -size 1536 \)		\
	    \( \! -name '*.gz' \) -type f > files.txt;		\
	  tar cf ../assets_raw/largefiles.tar -T files.txt;	\
	  cat files.txt | xargs rm;				\
	  cd ../assets_raw && tar xf largefiles.tar		\
	    && rm largefiles.tar;				\
	  cd ..;						\
	  mkdir -p assets_gz;					\
	  find assets -name '*.gz' -type f > files.txt;		\
	  tar cf assets_gz/gzfiles.tar -T files.txt;		\
	  cat files.txt | xargs rm;				\
	  cd assets_gz && tar xf gzfiles.tar			\
	    && rm gzfiles.tar;					\
	  rm ../assets/files.txt;				\
	fi
# Generate the directory tree for those directories.
# Install architecture dependents to lib/$(ANDROID_ABI).  This
# perculiar naming scheme is required to make Android preserve these
# binaries upon installation.
	$(AM_V_SILENT)								\
	for file in $(CROSS_BINS); do						\
	  if [ -x $$file ]; then      						\
	    filename=`basename $$file`; 					\
	    cp -f $$file install_temp/lib/$(ANDROID_ABI)/lib$${filename}.so;	\
	  fi 									\
	done
	$(AM_V_SILENT)						\
	for file in $(CROSS_LIBS); do				\
	  if [ -x $$file ]; then      				\
	    cp -f $$file install_temp/lib/$(ANDROID_ABI);	\
	  fi 							\
	done
# Next, produce a version of rcs2log befitting Android's naming
# conventions and shell interpreter location.
	$(AM_V_at) \
	sed 's|/bin/sh|/system/bin/sh|'					\
	 $(top_srcdir)/lib-src/rcs2log >				\
	 install_temp/lib/$(ANDROID_ABI)/librcs2log.so
	$(AM_V_at) chmod +x install_temp/lib/$(ANDROID_ABI)/librcs2log.so
ifneq ($(NDK_BUILD_SHARED),)
	$(AM_V_SILENT) cp -f $(NDK_BUILD_SHARED) \
	  install_temp/lib/$(ANDROID_ABI)
endif

emacs.apk-in: install_temp AndroidManifest.xml classes.dex
# Package everything.  Redirect the generated R.java to install_temp, as
# it must already have been generated as a prerequisite of
# classes.dex's.  If ANDROID_SDK_8_OR_EARLIER, compress those files
# which are smaller than 1536 blocks (i.e. 768 kib), the maximum the
# asset manager on such old systems can decompress.
#
# The elaborate dance with zip serves to disable the automatic
# decompression of *.gz files in aapt.
#
# One more consideration is that timestamps should be preserved in
# packaged libraries, as on Android 2.2 the package manager retains
# existing libraries from previous installations if a new package's
# libraries are not more recent.
	$(AM_V_AAPT)						\
	if [ -z "$(ANDROID_SDK_8_OR_EARLIER)" ]; then		\
	  $(AAPT) p -I "$(ANDROID_JAR)" -F $@			\
	    -f -M AndroidManifest.xml $(AAPT_ASSET_ARGS)	\
	    -A install_temp/assets			   	\
	    -S $(top_srcdir)/java/res -J install_temp;		\
	  cd install_temp;					\
	    $(AAPT) add ../$@ `find lib -type f`;		\
	else							\
	  echo "Packaging files not eligible for compression...">&2;\
	  $(AAPT) p -I "$(ANDROID_JAR)" -F $@			\
	    -f -M AndroidManifest.xml -A install_temp/assets_raw\
	    -S $(top_srcdir)/java/res -J install_temp -0 "";	\
	  echo "Packaging files eligible for compression...">&2;\
	  cd install_temp; find assets -type f 			\
	    | xargs $(ZIP) ../$@ &> /dev/null;			\
	  echo "Packaging files already compressed...">&2;	\
	  cd assets_gz; find assets -type f			\
	    | xargs $(ZIP) -0 ../../$@ &> /dev/null;		\
	  echo "Packaging shared libraries and code..." >&2;	\
	  cd ..; $(ZIP) ../$@ `find lib -type f`;		\
	fi
	$(AM_V_SILENT) $(AAPT) a $@ classes.dex
	$(AM_V_SILENT) rm -rf install_temp

# Makefile itself.
.PRECIOUS: $(top_builddir)/config.status Makefile
$(top_builddir)/config.status: $(top_srcdir)/configure.ac $(top_srcdir)/m4/*.m4
	$(MAKE) -C $(dir $@) $(notdir $@)
Makefile: $(top_builddir)/config.status $(top_srcdir)/java/Makefile.in
	$(MAKE) -C .. java/$@

# AndroidManifest.xml:
AndroidManifest.xml: $(top_srcdir)/configure.ac $(top_srcdir)/m4/*.m4 \
  $(srcdir)/AndroidManifest.xml.in
	pushd ..; ./config.status java/AndroidManifest.xml; popd

# R.java:
$(RESOURCE_FILE): $(RESOURCE_FILES)
	$(AM_V_GEN) $(AAPT) p -I "$(ANDROID_JAR)" -f	\
	  -J $(dir $@) -M AndroidManifest.xml		\
	  -S $(top_srcdir)/java/res

# Generate a list of libemacs's dependencies with each item ordered
# before its dependents for the startup process to load in advance, as
# older versions of the dynamic linker do not consider these libraries
# when resolving its imports.  The several following statements are
# executed from a recursive `make' run after shared libraries are
# generated.

ALL_DEPENDENCIES :=

ifneq (,$(filter cf-stamp-1,$(MAKECMDGOALS)))
# Don't be sidetracked by dependencies of shared libraries outside the
# ndk-build directory.
define get-dependencies
$(foreach x, \
$(and $(wildcard $(top_builddir)/cross/ndk-build/$1.so), \
      $(shell $(NDK_BUILD_READELF) -d \
	$(wildcard $(top_builddir)/cross/ndk-build/$1.so) \
        | sed -n 's/.*(NEEDED).*\[\(.*\.so\)\].*/\1/p')), \
$(basename $(notdir $(x))))
endef #get-dependencies
define resolve-one-dependency
$(foreach dependency,$(call get-dependencies,$1),\
  $(if $(findstring "$(dependency)",$(ALL_DEPENDENCIES)),,\
    $(call resolve-one-dependency,$(basename $(notdir $(dependency)))) \
    $(eval ALL_DEPENDENCIES := $(ALL_DEPENDENCIES) "$(dependency)",)))
endef #resolve-one-dependency
DEPENDENCIES := $(foreach file,$(NDK_BUILD_SHARED),\
		  $(basename $(notdir $(file))))
$(foreach file,$(DEPENDENCIES),\
  $(if $(findstring "$(file)",$(ALL_DEPENDENCIES)),,\
    $(call resolve-one-dependency,$(file)) \
    $(eval ALL_DEPENDENCIES := $(ALL_DEPENDENCIES) "$(file)",)))
endif

# EmacsConfig.java:
ifeq (${V},1)
AM_V_EMACSCONFIG =
else
AM_V_EMACSCONFIG = @$(info $.  GEN      org/gnu/emacs/EmacsConfig.java)
endif

.PHONY: cf-stamp-1
cf-stamp-1:
	$(AM_V_at) echo 'package org.gnu.emacs;\
public class EmacsConfig\
{\
/* This is a generated file.  Do not edit!  */\
public static final String[] EMACS_SHARED_LIBRARIES\
= {$(ALL_DEPENDENCIES)};\
}' | sed 's/\\//g' > globals.tmp
	$(AM_V_at) mkdir -p org/gnu/emacs
	$(AM_V_at) $(top_srcdir)/build-aux/move-if-change \
		globals.tmp org/gnu/emacs/EmacsConfig.java

# cf-stamp-1 is a phony target invoked in a second `make' instance after
# all shared libraries are compiled, because the computation of
# ALL_DEPENDENCIES in this instance of Make cannot be postponed until
# that stage.
#
# This recipe needs no dependency on $(NDK_BUILD_LIBS), since
# $(CROSS_LIBS) is a phony target that itself guarantees that they are
# up to date.
cf-stamp: $(CROSS_LIBS)
	$(AM_V_EMACSCONFIG) $(MAKE) cf-stamp-1
	$(AM_V_at) touch $@
$(CONFIG_FILE): cf-stamp; @true

# Make all class files depend on R.java and EmacsConfig.java being
# built.
$(CLASS_FILES): $(RESOURCE_FILE) $(CONFIG_FILE)

.SUFFIXES: .java .class
$(CLASS_FILES) &: $(JAVA_FILES)
	$(AM_V_JAVAC) $(JAVAC) $(JAVAFLAGS) $(JAVA_FILES) $(CONFIG_FILE)
	$(AM_V_SILENT) touch $(CLASS_FILES)

# N.B. that find must be called all over again in case javac generated
# nested classes.

ALL_CLASS_FILES =				\
  $(subst $$,\$$,$(shell find $(srcdir) -type f -name *.class))
ALL_CLASS_FILES_1 =

ifneq ($(builddir),$(srcdir))
# If the build directory is distinct from the source directory, also
# include generated class files located there.
ALL_CLASS_FILES_1 = \
  $(subst $$,\$$,$(shell find $(builddir) -type f -name *.class))
endif

classes.dex: $(CLASS_FILES) $(if $(IS_D8_R8), $(srcdir)/proguard.conf)
	$(AM_V_D8) $(D8) --classpath $(ANDROID_JAR)		\
	  $(ALL_CLASS_FILES) $(ALL_CLASS_FILES_1)		\
	  --output $(builddir)					\
	  --min-api $(ANDROID_MIN_SDK)				\
	  $(if $(filter false,$(ANDROID_DEBUGGABLE)),--release, \
                --debug) 					\
	  $(if $(IS_D8_R8),--pg-conf $(srcdir)/proguard.conf)

# When emacs.keystore expires, regenerate it with:
#
#  keytool -genkey -v -keystore emacs.keystore -alias "Emacs keystore" \
#   -keyalg RSA -sigalg  SHA1withRSA -keysize 2048 -validity 100000

.PHONY: clean maintainer-clean

$(APK_NAME): emacs.apk-in $(srcdir)/emacs.keystore
	$(AM_V_GEN)
	$(AM_V_SILENT) cp -f emacs.apk-in $@.unaligned
	$(AM_V_SILENT) $(JARSIGNER) $(SIGN_EMACS) $@.unaligned "Emacs keystore"
	$(AM_V_SILENT) $(ZIPALIGN) -f 4 $@.unaligned $@
# Signing must happen after alignment!
	$(AM_V_SILENT) $(APKSIGNER) $(SIGN_EMACS_V2) $@
	$(AM_V_SILENT) rm -f $@.unaligned *.idsig

# TAGS generation.

ETAGS = $(top_builddir)/lib-src/etags

$(ETAGS): FORCE
	$(MAKE) -C ../lib-src $(notdir $@)

tagsfiles = $(JAVA_FILES) $(RESOURCE_FILE)

.PHONY: tags FORCE
tags: TAGS
TAGS: $(ETAGS) $(tagsfiles)
	$(AM_V_GEN) $(ETAGS) $(tagsfiles)

clean:
	rm -f *.apk emacs.apk-in *.dex *.unaligned *.class *.idsig \
	  cf-stamp $(CONFIG_FILE)
	rm -rf install-temp $(RESOURCE_FILE) TAGS
	find . -name '*.class' $(FIND_DELETE)

maintainer-clean distclean bootstrap-clean: clean
	rm -f Makefile
